﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Shell32;

namespace FileMerge.Helpers
{
    public static class FileInfoHelper
    {
        private static KeyValuePair<string, string> property = new KeyValuePair<string, string>();

        private static Dictionary<string, string> properties = new Dictionary<string, string>();

        private static Dictionary<string, int> propertyDic = new Dictionary<string, int>();

        public static KeyValuePair<string, string> GetFileProperty(string path, string propName)
        {
            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                GetPropertyByShell32(new[] { path, propName });
            }
            else
            {
                var staThread = new Thread(new ParameterizedThreadStart(GetPropertyByShell32));

                staThread.SetApartmentState(ApartmentState.STA);

                staThread.Start(new[] { path, propName });
                staThread.Join();
            }

            return property;
        }

        public static Dictionary<string, string> GetFileProperties(string path)
        {
            if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
            {
                GetPropertiesByShell32(path);
            }
            else
            {
                var staThread = new Thread(new ParameterizedThreadStart(GetPropertiesByShell32));

                staThread.SetApartmentState(ApartmentState.STA);

                staThread.Start(path);
                staThread.Join();
            }

            return properties;
        }

        private static void GetPropertyByShell32(object para)
        {
            property = new KeyValuePair<string, string>();

            var paraArray = para as string[];

            if (paraArray == null || paraArray.Length != 2)
                return;

            var path = paraArray[0];
            var propName = paraArray[1];

            if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(propName))
                return;

            if (!propertyDic.ContainsKey(propName))
            {
                GetPropertiesByShell32(path);

                if (!properties.ContainsKey(propName))
                    return;

                property = new KeyValuePair<string, string>(propName, properties[propName]);

                return;
            }

            var shell = new ShellClass();

            try
            {
                Folder folder = shell.NameSpace(Path.GetDirectoryName(path));
                FolderItem item = folder.ParseName(Path.GetFileName(path));

                var propValue = folder.GetDetailsOf(item, propertyDic[propName]);

                property = new KeyValuePair<string, string>(propName, propValue);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        private static void GetPropertiesByShell32(object objectPath)
        {
            var shell = new ShellClass();
            var stringPath = objectPath.ToString();

            try
            {
                Folder folder = shell.NameSpace(Path.GetDirectoryName(stringPath));
                FolderItem item = folder.ParseName(Path.GetFileName(stringPath));

                int i = 0;

                while (true)
                {
                    var propName = folder.GetDetailsOf(null, i);

                    if (string.IsNullOrEmpty(propName))
                        break;

                    if (!propertyDic.ContainsKey(propName)) { propertyDic[propName] = i; }

                    properties[propName] = folder.GetDetailsOf(item, i);

                    i++;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
